建立好CI/CD的流程,除了可以減少人工的操作之外,也能透過安排好的測試等排程來讓專案更加的穩定。現在也有不同的服務來幫助建立CI/CD流程,例如GitLab還有今天要介紹的bitbucket pipelines
在進入大綱以前,先說明想要建立的自動化部署流程
主機在main branch中透git push將程式碼push到bitbucket上
bitbucket根據設置的pipelines.yml,先建立虛擬環境進行程式碼的測試
測試通過後,使用SSH連接到遠端主機,進到專案目錄
根據專案目錄的docker配置刪除舊容器,建立新的容器完成部署
而這篇文章的重點會放在bitbucket想要使用SSH操作遠端主機時需要注意的地方,而不是yml本身,所以今天重點都在如何完成第一到第三步的過程
首先我們從上面的Linode部分(遠端主機)來看,因為需要操作專案、使用docker建立容器與操作git,所以我們需要建立具備相關權限的群組與用戶。雖然在操作docker時很常需要用到root用戶,但是建立一個具有操作docker權限的用戶才是更安全的做法,而建立群組的好處是能將先前具有操作專案權限的用戶納入群組中
為了要讓Bitbucket能使用用戶透過SSH連到遠端主機,需要在sshd_config
檔案配置相關參數,以及將Bitbucket建立的公鑰放到遠端主機的authorized_keys
檔案中
接著來看下圖關於Bitbucket的配置,因為需要讓遠端主機能夠操作git,所以要將遠端主機的public key放到Bitbucket的Access keys配置中。並且我們需要在Bitbucket中配置SSH密鑰(不論是自己生成,還是拿本機的來用都可以)。生產或是拿來的公鑰,如同上段說的要拿去遠端主機的authorized_keys檔案,而私鑰則是之後pipeline需要用在SSH登入時驗證
最後來提及Repository variables配置的部分,因為是使用ssh_run鏡像,所以需要配置SSH_USER與SERVER才能讓pipeline使用SSH登入。而SSH_KEY如果在前面的步驟已經配置在Bitbucket的設定中,這邊可以不用填。而其他你需要在專案中用到的環境變數,如果是已經在遠端主機的檔案配置中的話,這邊可以不用配置,我這邊配置的是要給測試階段時,此時環境是Bitbucket的獨立虛擬環境,不會有遠端主機配置好的環境變數,所以還是要補上。
以上簡單的介紹一下流程,如果覺得還有哪邊覺得不是很清楚的話,可以看完底下詳細的步驟後,再回來把整個流程梳理一次邏輯~
getent group docker
# 如果有的話會顯示
docker:x:990:
useradd -m -s /bin/bash <username> #建立用戶
passwd <username> # 修改密碼
usermod -aG docker <username>
用戶的部分配置好了,接著要建立群組
為什麼要建立群組?而不是直接把所有需要的權限丟到剛剛的用戶就好了?
因為遠端主機的專案資料,不是只有這個部署的用戶要使用,因此建立群組然後讓其有專案資料的權限,最後再將用戶們納入群組之下
sudo groupadd <group_name>
usermod -aG <group_name> <username>
chown :<group_name> <file_path>
chmod g+rx <file_path>
chmod g+s <file_path>
這邊要注意:要從絕對路徑開始,直到專案目錄的每一層都要配置,並且要注意.git的隱藏資料夾有沒有套用到配置,沒有的話會部署失敗
接下來我們要確認新建立的用戶能夠使用SSH連線
sudo vim /etc/ssh/sshd_config
並且確認這些參數
PubkeyAuthentication yes # 表示能公鑰連線
PasswordAuthentication no # 不使用輸入密碼的方式登入
AllowUsers <user_name> # 確認能用ssh連線
最後來配置SSH密鑰認證時需要的檔案與權限
mkdir -p /<root_path>/<username>/.ssh
chown <username>:<username> /<root_path>/<username>/.ssh
chmod 700 /<root_path>/<username>/.ssh
touch /<root_path>/<username>/.ssh/authorized_keys
chown <username>:<username> /<root_path>/<username>/.ssh/authorized_keys
chmod 600 /<root_path>/<username>/.ssh/authorized_keys
同時我們也在這裡建立密鑰,公鑰之後要給Bitbucket的Access keys來使用遠程倉庫(repository)的權限
ssh-keygen -t rsa -b 4096 -C ""
在遠端主機的工作就告一段落了,我們接著來配置Bitbucket
先進到Repository settings中
將剛剛的公鑰(id_rsa)放到Bitbucket中
接著我們要來配置Repository settings中的SSH Keys
如果pipeline中需要使用多組SSH keys,那這邊可能可以跳過,直接全部配置在Repository variables上。但是我們就只有一組要認證,所以可以直接配置在這裡,後面的pipelines.yml可以省略一些步驟
我這邊因為有建立了所以長這樣,如果是第一次新增也會有按鈕讓你新增
不過輸入Private key時要注意,一定要連第一行跟最後一行都輸入進去
-----BEGIN OPENSSH PRIVATE KEY-----
xxxxxxxx
-----END OPENSSH PRIVATE KEY-----
然後用遠端主機的ip來建立know host
最後就來配置Repository variables
其中根據官方提供的ssh-run鏡像,SSH_USER跟SERVER是必須,其他的變數就根據自己需求來添加
至於pipelines.yml本身大致上的架構如下,畢竟今天重點不是在他身上,就不多做贅述,讀者再根據自己需求做調整
pipelines:
default:
- step:
name: Test
image: python:3.12-slim
caches:
- pip
script:
- apt-get update && apt-get install -y gcc python3-dev
# 這裡是相對於 repo root
- pip install -r <root_path>/requirements.txt
- cd <file_path>
- pytest -v
- step:
name: Deploy to Production
deployment: production
script:
- pipe: atlassian/ssh-run:0.8.1
variables:
SSH_USER: $SSH_USER
SERVER: $SERVER
COMMAND: >
set -e;
echo "當前用戶信息:" && whoami && groups;
echo "開始嘗試進入目錄:" &&
cd <file_path> &&
echo "成功進入目標目錄" &&
pwd &&
echo "開始執行部署步驟" &&
docker-compose ps > previous_state.txt &&
git pull origin main &&
docker-compose --env-file ../.env down &&
docker-compose --env-file ../.env build &&
docker-compose --env-file ../.env up -d &&
if ! docker-compose ps | grep -q "web.*Up"; then
echo "部署失敗,正在回滾..." &&
docker-compose down &&
cat previous_state.txt &&
exit 1;
fi &&
docker system prune -f --volumes &&
echo "部署完成!"
definitions:
services:
docker:
memory: 256
這是我第一次建立的CI/CD流程,中間失敗了50次以上,主要都是卡在對于權限的配置與SSH中遠端主機與Bitbucket所扮演的角色定位不夠了解,以及第一次寫COMMAND,不知道要用&&而是傻傻用;
整個流程大致上如下:
雖然文中是使用Bitbucket,但是了解了相關流程後,使用其他服務也是能照著相同的邏輯去處理~
https://support.atlassian.com/bitbucket-cloud/docs/set-up-pipelines-ssh-keys-on-linux/
https://support.atlassian.com/bitbucket-cloud/docs/configure-ssh-and-two-step-verification/
https://bitbucket.org/atlassian/ssh-run/src/master/?source=post_page
https://dev.to/manuelbosi/bitbucket-pipelines-configure-ssh-keys-1l56?source=post_page